package cn.itcast.starter.es.util;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author 虎哥
 */
public class ElasticClient {

    private final RestHighLevelClient client;
    private final String indexName;

    public ElasticClient(RestHighLevelClient client, String indexName) {
        this.client = client;
        this.indexName = indexName;
    }

    public <T> T getById(String id, Class<T> clazz) throws IOException {
        // 获取查询文档请求对象
        GetRequest request = new GetRequest(indexName, id);
        // 发出请求
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        // 解析
        String json = response.getSourceAsString();
        // 反序列化
        return JSON.parseObject(json, clazz);
    }

    public <T> List<T> searchHighlight(String searchField, String text, Class<T> clazz) throws IOException, NoSuchFieldException, IllegalAccessException {
        // 1.准备搜索参数对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 1.1.query
        searchSourceBuilder.query(QueryBuilders.matchQuery(searchField, text));
        // 1.2.高亮
        searchSourceBuilder.highlighter(new HighlightBuilder().field(searchField));

        // 2.准备搜索请求对象
        SearchRequest request = new SearchRequest(indexName);
        // 3.准备请求参数
        request.source(searchSourceBuilder);
        // 4.发请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 5.解析
        SearchHits searchHits = response.getHits();
        // 5.1.总条数
        // 5.2.获取数据
        SearchHit[] hits = searchHits.getHits();

        List<T> list = new ArrayList<T>(hits.length);

        for (SearchHit hit : hits) {
            // 5.3.解析source部分数据并反序列化为对象
            String json = hit.getSourceAsString();
            T t = JSON.parseObject(json, clazz);
            // 5.4.获取高亮部分
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField field = highlightFields.get(searchField);
            // 拼接高亮字段
            String note = StringUtils.join(field.getFragments());
            // 5.5.要把高亮结果放入t对象
            Field f = clazz.getDeclaredField(searchField);
            f.setAccessible(true);
            f.set(t, note);
            list.add(t);
        }
        return list;
    }
}
